//
// Created by wujehy on 2020/7/7.
//

#ifndef GEEJOAN_MYSQL_STATEMENT_H
#define GEEJOAN_MYSQL_STATEMENT_H

#include <mysql/field_types.h>
#include <vector>
#include "Exception.h"

typedef struct MYSQL_BIND MYSQL_BIND;
typedef struct MYSQL_STMT MYSQL_STMT;
typedef struct MYSQL_RES MYSQL_RES;

namespace GeeJoan
{
    namespace MySQL
    {
        class DataBase;

        class Statement
        {
            DataBase *hander = nullptr;
            std::string sql_str;
            MYSQL_BIND *bind_params = nullptr;
            MYSQL_BIND *bind_result = nullptr;
            MYSQL_STMT *stmt = nullptr;

            unsigned long *bind_length = nullptr; ///< 绑定数据的 长度
            bool *bind_is_null = nullptr;
            int m_psize = 0; ///< ? 参数的数量
            MYSQL_RES *prepare_meta_result = nullptr;
            int row_count = 0;
            int column_count = 0;
            std::vector<std::string> m_fields;///< 本次查询的字段名
        public:
            Statement(DataBase *hander, const std::string &sql, int size = 0);

            Statement(DataBase *hander, const char *sql, int size);

            void bind(int index, int &idata, enum_field_types type = MYSQL_TYPE_LONG);

            void bind(int index, int64_t &idata, enum_field_types type = MYSQL_TYPE_LONGLONG);

            void bind(int index, const std::string &stringdata, enum_field_types type = MYSQL_TYPE_STRING);

            void bind(int index, const char *str, enum_field_types type = MYSQL_TYPE_STRING);

            void bind(int index, float &fdata, enum_field_types type = MYSQL_TYPE_FLOAT);

            void bind(int index, double &fdata, enum_field_types type = MYSQL_TYPE_DOUBLE);

            /**
             * @brief　查询的时候绑定的查询数量
             * @param size
             */
            void result_size(int size);

            /**
             * @brief　查询的时候　绑定的　对象
             * @param index 序号　
             * @param buffer　
             * @param buffer_length
             * @param type 查询的类型
             */
            void result_bind(int index, void *buffer, int buffer_length, enum_field_types type = MYSQL_TYPE_DOUBLE);

            /**
             * @brief 直接执行 适用于　增删改
             * @return  影响的行数
             */
            int exec();

            /**
             * @brief 适用于查询
             * @return　
             */
            int query();

            /**
             * @brief 查询 并 返回是否有数据
             * @return 是否有数据 有则 查询一行 否则就关闭
             */
            bool Next();

            /**
             * @brief 关闭 本次 stmt
             */
            void reset();

            virtual ~Statement();

            int getRowCount() const;

            const std::vector<std::string> &getFields() const;
        };

    }
}

#endif //GEEJOAN_MYSQL_STATEMENT_H
